package entity

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/bytedance/sonic"
)

// ConditionParams 条件参数，用于存储工作流条件判断所需的参数
// 支持从JSON字符串创建和序列化，以及点号路径访问
type ConditionParams map[string]any

// NewConditionParams 从JSON字符串创建ConditionParams实例
// 参数:
//
//	jsonStr: JSON格式的字符串，包含条件参数的键值对
//
// 返回值:
//
//	ConditionParams: 解析后的条件参数实例
//	error: 解析过程中的错误信息
//
// 异常:
//
//	当jsonStr不是有效的JSON格式时返回解析错误
func NewConditionParams(jsonStr string) (ConditionParams, error) {
	// 步骤1: 初始化空的ConditionParams实例
	// 步骤2: 使用sonic库解析JSON字符串
	// 步骤3: 返回解析结果和错误信息

	var params ConditionParams

	// 处理空字符串或空JSON对象的情况
	if jsonStr == "" || jsonStr == "{}" {
		return make(ConditionParams), nil
	}

	// 使用sonic库进行JSON反序列化
	if err := sonic.Unmarshal([]byte(jsonStr), &params); err != nil {
		return nil, err
	}

	// 确保返回非nil的map
	if params == nil {
		params = make(ConditionParams)
	}

	return params, nil
}

func (c *ConditionParams) MarshalToString() (string, error) {
	if c == nil || len(*c) == 0 {
		return "{}", nil
	}

	b, err := sonic.Marshal(c)
	if err != nil {
		return "", err
	}

	return string(b), nil
}

func (c *ConditionParams) UnmarshalFromString(s string) error {
	return sonic.Unmarshal([]byte(s), c)
}

// GetValueByPath 通过点号路径获取值，支持嵌套对象和数组访问
// 使用sonic库的AST功能进行高效的JSON路径访问
// 例如："user.name", "config.settings.timeout", "users[0].name"
func (cp ConditionParams) GetValueByPath(path string) (any, bool) {
	// 步骤1: 检查路径是否为空
	// 步骤2: 将ConditionParams序列化为JSON字符串
	// 步骤3: 使用sonic的AST功能解析路径
	// 步骤4: 返回解析结果

	if path == "" {
		return nil, false
	}

	// 如果路径不包含点号和数组访问符，直接返回第一层的值
	if !strings.Contains(path, ".") && !strings.Contains(path, "[") {
		value, exists := cp[path]
		return value, exists
	}

	// 将ConditionParams序列化为JSON字符串
	jsonStr, err := cp.MarshalToString()
	if err != nil {
		return nil, false
	}

	// 解析路径为sonic可识别的路径参数
	pathArgs := cp.parsePath(path)
	if len(pathArgs) == 0 {
		return nil, false
	}

	// 使用sonic的GetFromString方法获取值
	node, err := sonic.GetFromString(jsonStr, pathArgs...)
	if err != nil {
		return nil, false
	}

	// 检查节点是否存在
	if err := node.Check(); err != nil {
		return nil, false
	}

	// 获取节点的接口值
	value, err := node.Interface()
	if err != nil {
		return nil, false
	}

	return value, true
}

// parsePath 解析点号路径为sonic可识别的路径参数
// 例如："user.profile.settings[0].name" -> ["user", "profile", "settings", 0, "name"]
func (cp ConditionParams) parsePath(path string) []any {
	// 步骤1: 分割路径为各个部分
	// 步骤2: 处理每个部分，识别字符串键和数组索引
	// 步骤3: 返回sonic格式的路径参数

	var pathArgs []any
	parts := strings.Split(path, ".")

	for _, part := range parts {
		// 检查是否包含数组访问
		if strings.Contains(part, "[") && strings.Contains(part, "]") {
			// 解析数组访问："users[0]" -> "users", 0
			openBracket := strings.Index(part, "[")
			closeBracket := strings.Index(part, "]")

			if openBracket == -1 || closeBracket == -1 || closeBracket <= openBracket {
				continue
			}

			key := part[:openBracket]
			indexStr := part[openBracket+1 : closeBracket]

			// 添加对象键
			if key != "" {
				pathArgs = append(pathArgs, key)
			}

			// 添加数组索引
			if index, err := strconv.Atoi(indexStr); err == nil {
				pathArgs = append(pathArgs, index)
			}
		} else {
			// 普通字符串键
			pathArgs = append(pathArgs, part)
		}
	}

	return pathArgs
}

// GetTypedValue 根据指定类型获取并转换值
func (cp ConditionParams) GetTypedValue(path string, valueType string) (any, bool) {
	value, exists := cp.GetValueByPath(path)
	if !exists {
		return nil, false
	}

	switch valueType {
	case "string":
		return fmt.Sprintf("%v", value), true
	case "int":
		return cp.toInt(value)
	case "float":
		return cp.toFloat64(value)
	case "bool":
		return cp.toBool(value)
	case "array":
		if arr, ok := value.([]any); ok {
			return arr, true
		}
		return nil, false
	case "object":
		if obj, ok := value.(map[string]any); ok {
			return obj, true
		}
		return nil, false
	default:
		return value, true
	}
}

// toInt 将值转换为int
func (cp ConditionParams) toInt(value any) (int, bool) {
	switch v := value.(type) {
	case int:
		return v, true
	case int8:
		return int(v), true
	case int16:
		return int(v), true
	case int32:
		return int(v), true
	case int64:
		return int(v), true
	case uint:
		return int(v), true
	case uint8:
		return int(v), true
	case uint16:
		return int(v), true
	case uint32:
		return int(v), true
	case uint64:
		return int(v), true
	case float32:
		return int(v), true
	case float64:
		return int(v), true
	case string:
		if i, err := strconv.Atoi(v); err == nil {
			return i, true
		}
	}
	return 0, false
}

// toFloat64 将值转换为float64
func (cp ConditionParams) toFloat64(value any) (float64, bool) {
	switch v := value.(type) {
	case int:
		return float64(v), true
	case int8:
		return float64(v), true
	case int16:
		return float64(v), true
	case int32:
		return float64(v), true
	case int64:
		return float64(v), true
	case uint:
		return float64(v), true
	case uint8:
		return float64(v), true
	case uint16:
		return float64(v), true
	case uint32:
		return float64(v), true
	case uint64:
		return float64(v), true
	case float32:
		return float64(v), true
	case float64:
		return v, true
	case string:
		if f, err := strconv.ParseFloat(v, 64); err == nil {
			return f, true
		}
	}
	return 0, false
}

// toBool 将值转换为bool
func (cp ConditionParams) toBool(value any) (bool, bool) {
	switch v := value.(type) {
	case bool:
		return v, true
	case string:
		if b, err := strconv.ParseBool(v); err == nil {
			return b, true
		}
		// 支持常见的字符串表示
		lower := strings.ToLower(v)
		if lower == "true" || lower == "yes" || lower == "1" {
			return true, true
		}
		if lower == "false" || lower == "no" || lower == "0" {
			return false, true
		}
	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		return fmt.Sprintf("%v", v) != "0", true
	case float32, float64:
		return fmt.Sprintf("%v", v) != "0", true
	}
	return false, false
}
